/*
 * Created on Sat Sep 16 2017
 * 
 * Copyright (c) 2017 jianglinjie
 */
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _NetTask = require('../task/NetTask');

var _NetTask2 = _interopRequireDefault(_NetTask);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var NetClient = function () {
  function NetClient(strategy) {
    _classCallCheck(this, NetClient);

    this.handlers = new Set();

    this.strategy = strategy;
  }

  _createClass(NetClient, [{
    key: 'addHandler',
    value: function addHandler(handler) {
      this.handlers.add(handler);
    }
  }, {
    key: 'removeHandler',
    value: function removeHandler(handler) {
      this.handlers.delete(handler);
    }
  }, {
    key: 'start',
    value: function () {
      var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(request) {
        var finalRequest, body, _body;

        return regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                _context.next = 2;
                return this._createFinalRequest(request);

              case 2:
                finalRequest = _context.sent;
                _context.prev = 3;
                _context.next = 6;
                return this._startTask(finalRequest);

              case 6:
                body = _context.sent;
                return _context.abrupt('return', body);

              case 10:
                _context.prev = 10;
                _context.t0 = _context['catch'](3);
                _context.next = 14;
                return this._handleError(_context.t0, request, finalRequest);

              case 14:
                _body = _context.sent;
                return _context.abrupt('return', _body);

              case 16:
              case 'end':
                return _context.stop();
            }
          }
        }, _callee, this, [[3, 10]]);
      }));

      function start(_x) {
        return _ref.apply(this, arguments);
      }

      return start;
    }()
  }, {
    key: '_startTask',
    value: function () {
      var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(request) {
        var task, response, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, handler, verifyResult;

        return regeneratorRuntime.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                task = new _NetTask2.default(request, this.strategy);
                _context2.next = 3;
                return task.start();

              case 3:
                response = _context2.sent;
                _iteratorNormalCompletion = true;
                _didIteratorError = false;
                _iteratorError = undefined;
                _context2.prev = 7;
                _iterator = this.handlers[Symbol.iterator]();

              case 9:
                if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
                  _context2.next = 19;
                  break;
                }

                handler = _step.value;
                _context2.next = 13;
                return handler.verifyResponse(response);

              case 13:
                verifyResult = _context2.sent;

                if (verifyResult.ok) {
                  _context2.next = 16;
                  break;
                }

                throw verifyResult.error;

              case 16:
                _iteratorNormalCompletion = true;
                _context2.next = 9;
                break;

              case 19:
                _context2.next = 25;
                break;

              case 21:
                _context2.prev = 21;
                _context2.t0 = _context2['catch'](7);
                _didIteratorError = true;
                _iteratorError = _context2.t0;

              case 25:
                _context2.prev = 25;
                _context2.prev = 26;

                if (!_iteratorNormalCompletion && _iterator.return) {
                  _iterator.return();
                }

              case 28:
                _context2.prev = 28;

                if (!_didIteratorError) {
                  _context2.next = 31;
                  break;
                }

                throw _iteratorError;

              case 31:
                return _context2.finish(28);

              case 32:
                return _context2.finish(25);

              case 33:
                return _context2.abrupt('return', response.body);

              case 34:
              case 'end':
                return _context2.stop();
            }
          }
        }, _callee2, this, [[7, 21, 25, 33], [26,, 28, 32]]);
      }));

      function _startTask(_x2) {
        return _ref2.apply(this, arguments);
      }

      return _startTask;
    }()

    //注入公共的header和url参数

  }, {
    key: '_createFinalRequest',
    value: function () {
      var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(request) {
        var extraUrlParam, finalRequest, extraHeaders;
        return regeneratorRuntime.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                _context3.next = 2;
                return this._getExtraUrlParam(request);

              case 2:
                extraUrlParam = _context3.sent;
                finalRequest = request.clone();

                finalRequest.urlParam = _extends({}, extraUrlParam, finalRequest.urlParam);

                _context3.next = 7;
                return this._getExtraHeaders(finalRequest);

              case 7:
                extraHeaders = _context3.sent;

                finalRequest.headers = _extends({}, extraHeaders, finalRequest.headers);
                return _context3.abrupt('return', finalRequest);

              case 10:
              case 'end':
                return _context3.stop();
            }
          }
        }, _callee3, this);
      }));

      function _createFinalRequest(_x3) {
        return _ref3.apply(this, arguments);
      }

      return _createFinalRequest;
    }()
  }, {
    key: '_getExtraUrlParam',
    value: function () {
      var _ref4 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(request) {
        var finalExtraUrlParam, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, handler, extraUrlParam;

        return regeneratorRuntime.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                finalExtraUrlParam = {};
                _iteratorNormalCompletion2 = true;
                _didIteratorError2 = false;
                _iteratorError2 = undefined;
                _context4.prev = 4;
                _iterator2 = this.handlers[Symbol.iterator]();

              case 6:
                if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
                  _context4.next = 15;
                  break;
                }

                handler = _step2.value;
                _context4.next = 10;
                return handler.injectExtraURLParam(request);

              case 10:
                extraUrlParam = _context4.sent;


                finalExtraUrlParam = _extends({}, finalExtraUrlParam, extraUrlParam);

              case 12:
                _iteratorNormalCompletion2 = true;
                _context4.next = 6;
                break;

              case 15:
                _context4.next = 21;
                break;

              case 17:
                _context4.prev = 17;
                _context4.t0 = _context4['catch'](4);
                _didIteratorError2 = true;
                _iteratorError2 = _context4.t0;

              case 21:
                _context4.prev = 21;
                _context4.prev = 22;

                if (!_iteratorNormalCompletion2 && _iterator2.return) {
                  _iterator2.return();
                }

              case 24:
                _context4.prev = 24;

                if (!_didIteratorError2) {
                  _context4.next = 27;
                  break;
                }

                throw _iteratorError2;

              case 27:
                return _context4.finish(24);

              case 28:
                return _context4.finish(21);

              case 29:
                return _context4.abrupt('return', finalExtraUrlParam);

              case 30:
              case 'end':
                return _context4.stop();
            }
          }
        }, _callee4, this, [[4, 17, 21, 29], [22,, 24, 28]]);
      }));

      function _getExtraUrlParam(_x4) {
        return _ref4.apply(this, arguments);
      }

      return _getExtraUrlParam;
    }()
  }, {
    key: '_getExtraHeaders',
    value: function () {
      var _ref5 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(request) {
        var finalExtraHeaders, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, handler, extraHeaders;

        return regeneratorRuntime.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                finalExtraHeaders = {};
                _iteratorNormalCompletion3 = true;
                _didIteratorError3 = false;
                _iteratorError3 = undefined;
                _context5.prev = 4;
                _iterator3 = this.handlers[Symbol.iterator]();

              case 6:
                if (_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done) {
                  _context5.next = 15;
                  break;
                }

                handler = _step3.value;
                _context5.next = 10;
                return handler.injectExtraHeaders(request);

              case 10:
                extraHeaders = _context5.sent;


                finalExtraHeaders = _extends({}, finalExtraHeaders, extraHeaders);

              case 12:
                _iteratorNormalCompletion3 = true;
                _context5.next = 6;
                break;

              case 15:
                _context5.next = 21;
                break;

              case 17:
                _context5.prev = 17;
                _context5.t0 = _context5['catch'](4);
                _didIteratorError3 = true;
                _iteratorError3 = _context5.t0;

              case 21:
                _context5.prev = 21;
                _context5.prev = 22;

                if (!_iteratorNormalCompletion3 && _iterator3.return) {
                  _iterator3.return();
                }

              case 24:
                _context5.prev = 24;

                if (!_didIteratorError3) {
                  _context5.next = 27;
                  break;
                }

                throw _iteratorError3;

              case 27:
                return _context5.finish(24);

              case 28:
                return _context5.finish(21);

              case 29:
                return _context5.abrupt('return', finalExtraHeaders);

              case 30:
              case 'end':
                return _context5.stop();
            }
          }
        }, _callee5, this, [[4, 17, 21, 29], [22,, 24, 28]]);
      }));

      function _getExtraHeaders(_x5) {
        return _ref5.apply(this, arguments);
      }

      return _getExtraHeaders;
    }()
  }, {
    key: '_handleError',
    value: function () {
      var _ref6 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(error, orginalRequest, finalRequest) {
        var retry, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, handler, result, newFinalRequest, body;

        return regeneratorRuntime.wrap(function _callee6$(_context6) {
          while (1) {
            switch (_context6.prev = _context6.next) {
              case 0:
                retry = false;
                _iteratorNormalCompletion4 = true;
                _didIteratorError4 = false;
                _iteratorError4 = undefined;
                _context6.prev = 4;
                _iterator4 = this.handlers[Symbol.iterator]();

              case 6:
                if (_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done) {
                  _context6.next = 15;
                  break;
                }

                handler = _step4.value;
                _context6.next = 10;
                return handler.handleError(error, finalRequest);

              case 10:
                result = _context6.sent;

                if (result.retry) {
                  //只要有一个要求重试 就重试
                  retry = true;
                }

              case 12:
                _iteratorNormalCompletion4 = true;
                _context6.next = 6;
                break;

              case 15:
                _context6.next = 21;
                break;

              case 17:
                _context6.prev = 17;
                _context6.t0 = _context6['catch'](4);
                _didIteratorError4 = true;
                _iteratorError4 = _context6.t0;

              case 21:
                _context6.prev = 21;
                _context6.prev = 22;

                if (!_iteratorNormalCompletion4 && _iterator4.return) {
                  _iterator4.return();
                }

              case 24:
                _context6.prev = 24;

                if (!_didIteratorError4) {
                  _context6.next = 27;
                  break;
                }

                throw _iteratorError4;

              case 27:
                return _context6.finish(24);

              case 28:
                return _context6.finish(21);

              case 29:
                if (!retry) {
                  _context6.next = 39;
                  break;
                }

                _context6.next = 32;
                return this._createFinalRequest(orginalRequest);

              case 32:
                newFinalRequest = _context6.sent;
                _context6.next = 35;
                return this._startTask(newFinalRequest);

              case 35:
                body = _context6.sent;
                return _context6.abrupt('return', body);

              case 39:
                throw error;

              case 40:
              case 'end':
                return _context6.stop();
            }
          }
        }, _callee6, this, [[4, 17, 21, 29], [22,, 24, 28]]);
      }));

      function _handleError(_x6, _x7, _x8) {
        return _ref6.apply(this, arguments);
      }

      return _handleError;
    }()
  }]);

  return NetClient;
}();

exports.default = NetClient;